﻿using Ice.Extension;
using IoTClient.Clients.Modbus;
using IoTClient.Common.Helpers;
using Polly;
using Serilog;
using Sunny.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TouchSocket.Core;

namespace ArcLightProtector
{
    public partial class SensorPointControl : UserControl
    {

        public string ProtectorName { get; set; }

        public SensorPointData PointData { get; set; }

        private Control _control;

        public event Action OnSettingValueBefore;
        public event Action OnSettingValueAfter;

        private ModbusRtuClient _client;
        private byte _slaveId;
        private CancellationTokenSource _tokenSource = new CancellationTokenSource();


        private List<UILight> _lights = new List<UILight>();
        private List<Label> _bitLabels = new List<Label>();

        public SensorPointControl()
        {
            InitializeComponent();
            button1.Click += Button1_Click;
        }

        public void SetModbusClient(byte slaveId, ModbusRtuClient client)
        {
            _slaveId = slaveId;
            _client = client;
        }

        private async void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                OnSettingValueBefore?.Invoke();
                string value = "";
                if (_control is TextBox tb) value = tb.Text;
                var dataType = PointData.DataType;
                if (string.IsNullOrEmpty(PointData.ControlType) && dataType == "ushort" || dataType == "short")
                {
                    var ushortValue = ushort.Parse(value);

                    if (PointData.MinValue.HasValue)
                    {
                        if (ushortValue < PointData.MinValue || ushortValue > PointData.MaxValue)
                        {
                            throw new Exception($"{PointData.Name} 的值必须在 {PointData.MinValue}-{PointData.MaxValue}之间");
                        }
                    }
                    await Task.Delay(500);
                    await Policy.Handle<Exception>().RetryAsync(3).ExecuteAsync(async () =>
                     {
                         await Task.Run(() =>
                         {
                             if (ProtectorName == "导轨弧光保护")
                             {
                                 var buffer = new List<byte> { _slaveId, 0x23, 00, 00, 00, 01, 04, 00, 00 };
                                 ushortValue = (ushort)(ushortValue * 100);
                                 var bytes = BitConverter.GetBytes(ushortValue);
                                 buffer.Add(bytes[1]);
                                 buffer.Add(bytes[0]);
                                 var command = CRC16.GetCRC16(buffer.ToArray());
                                 var result = _client.SendPackageReliable(command);
                                 Log.Information("电流定值:" + BitConverter.ToString(command) + " -> " + BitConverter.ToString(result.Value));
                                 if (result.Value.Length < 5) throw new Exception("设置错误");
                             }
                         });
                     });
                }
                else if (PointData.ControlType == "combobox" && _control is ComboBox cbo)
                {
                    var label = cbo.Text;
                    var key = "0";
                    foreach (var item in PointData.MapDic)
                    {
                        if (item.Value == label)
                        {
                            key = item.Key;
                            break;
                        }
                    }
                    var ushortValue = ushort.Parse(key);
                    await Task.Delay(1000);
                    await Policy.Handle<Exception>().RetryAsync(3).ExecuteAsync(async () =>
                    {
                        //  await _client.WriteSingleRegisterAsync(_slaveId, PointData.Address, ushortValue, 500, _tokenSource.Token);
                    });
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                OnSettingValueAfter?.Invoke();
            }
        }

        private void SetValue1()
        {
            if (ProtectorName != "导轨弧光保护") return;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (PointData.Readonly)
            {
                button1.Visible = false;
            }

            //初始化控件
            lblName.Text = PointData.Name;
            var controlType = PointData.ControlType;
            if (string.IsNullOrEmpty(controlType))
            {
                var tb = new TextBox() { Dock = DockStyle.Fill, TextAlign = HorizontalAlignment.Center };
                tb.BorderStyle = BorderStyle.FixedSingle;
                panel1.Controls.Add(tb);
                _control = tb;
                if (PointData.Readonly)
                {
                    tb.ReadOnly = true;
                }
            }
            else if (controlType == "bit")
            {
                var font = new Font("黑体", 9);

                //TableLayoutPanel tableFlayoutPanel = new TableLayoutPanel()
                //{
                //    Dock = DockStyle.Fill
                //};

                //tableFlayoutPanel.RowCount = 2;
                //tableFlayoutPanel.ColumnCount = 2;
                //for (int i = 0; i < tableFlayoutPanel.ColumnCount; i++)
                //{
                //    tableFlayoutPanel.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.Percent, Width = 50 });
                //}

                //for (int i = 0; i < tableFlayoutPanel.RowCount; i++)
                //{
                //    tableFlayoutPanel.RowStyles.Add(new RowStyle() { SizeType = SizeType.Percent, Height = 50 });
                //}

                for (int i = 0; i < PointData.Length; i++)
                {
                    var light = new UILight()
                    {
                        Text = i.ToString(),
                        Width = 20,
                        Height = 20,
                        ShowText = false,
                        Font = font,
                        State = UILightState.Off,
                        Left = 20 * (i)
                    };

                    var label = new Label()
                    {
                        Font = font,
                        Text = i.ToString(),
                        AutoSize = true,
                        ForeColor = Color.Gray,
                        TextAlign = ContentAlignment.MiddleCenter,
                    };

                    if (PointData.MapDic != null)
                    {
                        var mapValue = PointData.GetMapValue(i.ToString());
                        label.Text = mapValue;
                    }
                    _lights.Add(light);
                    _bitLabels.Add(label);

                    //tableFlayoutPanel.Controls.Add(light);
                    _control = light;
                }
                panel1.Controls.Add(_control);
                lblUnit.Width = 20;
            }
            else if (controlType == "combobox") //下拉框
            {
                var cbo = new ComboBox() { Dock = DockStyle.Fill, DropDownStyle = ComboBoxStyle.DropDownList };
                var values = PointData.MapDic.Values;
                cbo.Items.AddRange(values.ToArray());
                panel1.Controls.Add(cbo);
                _control = cbo;
            }

            lblUnit.Text = PointData.Unit;
        }

        public void RefreshValue()
        {
            var canUpdate = true;
            if (_control is TextBox tb)
            {
                tb.Invoke(x =>
                {
                    if (x.Focused)
                    {
                        canUpdate = false;
                    }
                });
                if (!canUpdate) return;
                if (string.IsNullOrEmpty(PointData.Value?.ToString()))
                {
                    tb.InvokeText("");
                    return;
                }
                if (string.IsNullOrEmpty(PointData.MapInfo))
                {
                    //原始值
                    tb.InvokeText(PointData.Value.ToString());
                }
                else
                {
                    tb.InvokeText(PointData.GetMapValue(PointData.Value.ToString()));
                }
            }
            else if (_control is UILight)
            {
                var value = (ushort)PointData.Value;
                var bits = new BitArray(BitConverter.GetBytes(value));
                //for (int i = 0; i < PointData.Length; i++)
                //{
                //    //sb.Append((bits[i] ? "1" : "0") + " ");
                //    _lights[i].State = bits[i] ? UILightState.On : UILightState.Off;
                //}
                _lights[0].State = bits[PointData.BitPosition] ? UILightState.On : UILightState.Off;
                return;
            }
            else if (_control is Label)
            {
                var value = (ushort)PointData.Value;
                var bits = new BitArray(BitConverter.GetBytes(value));
                for (int i = 0; i < PointData.Length; i++)
                {
                    //sb.Append((bits[i] ? "1" : "0") + " ");
                    _bitLabels[i].Invoke(x =>
                    {
                        x.ForeColor = bits[i] ? Color.Red : Color.Gray;
                    });
                }
                return;
            }
            else if (_control is ComboBox cbo)
            {
                cbo.Invoke(x =>
                {
                    if (x.Focused)
                    {
                        canUpdate = false;
                    }
                });
                if (!canUpdate) return;
                var key = PointData.Value.ToString();
                var label = PointData.GetMapValue(key);
                cbo.Invoke(x =>
                {
                    x.Text = label;
                });
            }
        }

    }
}
